package com.seguriapp.complaints.gwt.server;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import net.customware.gwt.dispatch.server.ExecutionContext;
import net.customware.gwt.dispatch.shared.DispatchException;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.restlet.resource.ClientResource;

import com.seguriapp.common.config.GlobalConfigLoader;
import com.seguriapp.common.gwt.server.AbstractSeguriAppHandler;
import com.seguriapp.complaints.gwt.shared.SaveComplaintMediaDataAction;
import com.seguriapp.complaints.gwt.shared.SaveComplaintMediaDataResult;
import com.seguriapp.entities.MediaContent;
import com.seguriapp.util.Util;

public class SaveComplaintMediaDataHandler extends AbstractSeguriAppHandler<SaveComplaintMediaDataAction, SaveComplaintMediaDataResult> {

  private static final Logger LOGGER = Logger.getLogger(SaveComplaintMediaDataHandler.class);

  public Class<SaveComplaintMediaDataAction> getActionType() {
    return SaveComplaintMediaDataAction.class;
  }

  public SaveComplaintMediaDataResult execute(final SaveComplaintMediaDataAction action, final ExecutionContext context) throws DispatchException {

    final SaveComplaintMediaDataResult result = new SaveComplaintMediaDataResult();
    try {
      final String url = GlobalConfigLoader.getInstance().getGlobalConfig().getBackEndUrl()
          .concat(GlobalConfigLoader.getInstance().getGlobalConfig().getSaveComplaintMedia());
      final ClientResource resource = new ClientResource(url);
      if (renameAndDeleteMediaFiles(action)) {
        final String resultStr = resource.post(convertDataToJsonString(action)).getText();
        LOGGER.info("Data received : \n" + resultStr);
        result.setSuccess(Boolean.parseBoolean(resultStr));
      } else {
        result.setSuccess(false);
      }
    } catch (Exception e) {
      LOGGER.error("Error al registrar media de denuncia", e);
    }
    return result;
  }

  private boolean renameAndDeleteMediaFiles(final SaveComplaintMediaDataAction action) {
    boolean valid = true;
    for (MediaContent media : action.getMediaList()) {
      final File file = new File(Util.DESTINATION_DIR_PATH, media.getContent());
      if (file.exists() && file.isFile()) {
        InputStream is = null;
        FileOutputStream fos = null;
        try {
          is = new FileInputStream(file);
          fos = new FileOutputStream(new File(Util.DESTINATION_DIR_PATH, action.getComplaintId() + "-" + media.getContent()));
          IOUtils.copy(is, fos);
          media.setContent(action.getComplaintId() + "-" + media.getContent());
        } catch (FileNotFoundException e) {
          valid = false;
          LOGGER.error("Error copying file", e);
        }  catch (IOException ioex) {
          valid = false;
          LOGGER.error("Error copying file", ioex);
        } catch (Exception ex) {
          valid = false;
          LOGGER.error("Error copying file", ex);
        } finally {
          try {
            if (fos != null) {
              fos.close();
            }
            if (is != null) {
              is.close();
            }
          } catch (IOException ignored) {
          }
        }
        file.delete();
      }
    }

    for (MediaContent media : action.getMediaDeletedList()) {
      final File file = new File(Util.DESTINATION_DIR_PATH, media.getContent());
      if (file.exists() && file.isFile()) {
        file.delete();
      }
    }
    return valid;
  }

  private String convertDataToJsonString(final SaveComplaintMediaDataAction action) {
    final JSONObject obj = new JSONObject();
    try {
      obj.put("complaintId", action.getComplaintId());
      final List<Map<?, ?>> l1 = new LinkedList<Map<?, ?>>();
      for (final MediaContent media : action.getMediaList()) {
        l1.add(media.toJsonString());
      }
      try {
        obj.put("media", l1);
      } catch (JSONException e) {
        LOGGER.error(e.getMessage(), e);
      }
    } catch (JSONException e) {
      LOGGER.error("Error al convertir media content a json", e);
    }
    LOGGER.info("Sending Data : \n" + obj.toString());
    return obj.toString();
  }

}
